<?php

/*
Aurus CMS - free OOP CMS
Copyright (C) 2010  Nestor Yanchuk

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('ROOT'))
die();

class Url {

	static public $keyValueSeparator = '-';
	static public $partsSeparator = '/';
	static public $disallowedCharReplacement = '_';
	static public $postfix = '.html';
	static private $model = '';
	static private $urlParts = array();
	static private $disallowedChar = array();

	private static function init() {
		self::$disallowedChar = array(
		'<' => '', '>' => '', '#' => '', '%' => '', '"' => '', '\'' => '', '{' => '', '}' => '', '|' => '', '\\' => '', '^' => '', '[' => '', ']' => '', '`' => '', ';' => '', '?' => '', ':' => '', '@' => '', '&' => '', '=' => '', '+' => '', '$' => '', ',' => '', ' ' => '+', self::$keyValueSeparator => self::$disallowedCharReplacement, self::$partsSeparator => self::$disallowedCharReplacement,
		);

		if (Config::get('key_value_saperator', 'class_url')) {
			self::$keyValueSeparator = Config::get('key_value_saperator', 'class_url');
		}
		if (Config::get('parameter_saperator', 'class_url')) {
			self::$partsSeparator = Config::get('parameter_saperator', 'class_url');
		}
		if (Config::get('href_end', 'class_url')) {
			self::$postfix = Config::get('href_end', 'class_url');
		}
	}

	public static function getModel() {
		return self::$model;
	}

	public static function getUrlPart($offset) {
		if (isset(self::$urlParts[$offset])) {
			return self::$urlParts[$offset];
		}
		return '';
	}

	public static function parseGet() {
		self::init();

		if (!isset($_SERVER['QUERY_STRING']) || strpos($_SERVER['QUERY_STRING'], '=') || strlen($_SERVER['QUERY_STRING']) < 2) {
			return;
		}

		$str = $_SERVER['QUERY_STRING'];

		$postLen = strlen(self::$postfix);
		if (substr($str, -$postLen) == self::$postfix) {
			$str = substr($str, 0, -$postLen);
		}

		$urlParts = array();
		foreach (explode('/', $str) as $part) {
			if (is_int(strpos($part, self::$keyValueSeparator))) {
				$urlParts [] = $part;
			} else {
				self::$urlParts [] = $part;
			}
		}

		if (isset(self::$urlParts[0])) {
			self::$model = self::$urlParts[0];
		}

		$str = join('/', $urlParts);

		if ($str) {
			$p = explode(self::$partsSeparator, $str);
			foreach ($p as $kv) {
				$kva = explode(self::$keyValueSeparator, $kv);
				$_GET[$kva[0]] = $kva[1];
			}
		}
	}

	private function getUrlPrefix($useLR) {
		if (boolean(Config::get('furl'))) {
			if ($useLR) {
				$prefix = rtrim(LINK_ROOT, '/');
			} else {
				$prefix = '/';
			}
		} else {
			if ($useLR) {
				$prefix = rtrim(LINK_ROOT, '/');
			} else {
				$prefix = '/?';
			}
		}
		return $prefix;
	}

	public static function formatUrl($model, $urlparams, $useLR = true, $urlParts = array()) {
		$ret = array();
		$prefix[] = self::getUrlPrefix($useLR);

		$prefix[] = $model;

		foreach ($urlparams as $key => $val) {
			$ret[] = self::encodeAndJoinKeyAndValue($key, $val);
		}

		if (is_string($urlParts) && $urlParts) {
			$urlParts = array($urlParts);
		}

		array_map(array(__CLASS__, 'encode'), $urlParts);

		if (sizeof($urlParts)) {
			$ret = array_merge($ret, $urlParts);
		}

		array_clean($ret);

		return Filter::apply(join(self::$partsSeparator, $prefix) . self::$partsSeparator . join(self::$partsSeparator, $ret) . self::$postfix, 'format_url');
	}

	private function encodeAndJoinKeyAndValue($key, $value) {
		return self::encode($key) . self::$keyValueSeparator . self::encode($value);
	}

	private function encode($string) {
		$string = strtr($string, self::$disallowedChar);
		$string = trim(self::replaceRepeatedChar($string, '+'), '+');

		$ret = '';

		for ($i = 0, $n = strlen($string); $i < $n; $i++) {
			$c = $string[$i];
			$char = ord($c);

			if (($char > 47 && $char < 58) || // 0..9
			($char > 64 && $char < 91) || // A..Z
			($char > 96 && $char < 123) || // a..z
			($char > 39 && $char < 42) || // ()
			$char === 95 || //_
			$char === 46 || //.
			$char === 126 || //~
			$char === 43   //+
			) {
				$ret .= $c;
			} else {
				$ret .= urlencode($c);
			}
		}
		return $ret;
	}

	private function replaceRepeatedChar($str, $char) {
		while (strpos($str, $char . $char)) {
			$str = str_replace($char . $char, $char, $str);
		}
		return $str;
	}

}